package com.jason.library.coroutine

import kotlinx.coroutines.*

//协程
object CoroutineMain {

    @JvmStatic
    fun main(args: Array<String>) {
        //coroutineFun()
        //coroutineBlock()
        //coroutineRunBlocking()
        //coroutineExampleRun()
        //coroutineLight();
        //globalCoroutine();

        //coroutinesAsync()
        //withContextFun()
        //coroutineTryCatch()
        asyncTryCatch()
    }
}

fun coroutineFun() {
    var job = GlobalScope.launch {//在后台启动一个新的协程并继续
        delay(1000L) // 非阻塞的等待 1 秒钟（默认时间单位是毫秒）
        println("World!") // 在延迟后打印输出
    }

    println("job.isActive = "+job.isActive)
    println("job.isCancelled = "+job.isCancelled)
    println("job.isCompleted = "+job.isCompleted)
    println("Hello,") // 协程已在等待时主线程还在继续

    job.cancel() //关闭
    println("execute cancel")
    println("job.isActive = "+job.isActive)
    println("job.isCancelled = "+job.isCancelled)
    println("job.isCompleted = "+job.isCompleted)

    job.start() //开始执行, 前面已经被关闭了，无法执行
    println("execute start")
    println("job.isActive = "+job.isActive)
    println("job.isCancelled = "+job.isCancelled)
    println("job.isCompleted = "+job.isCompleted)

    Thread.sleep(2000L) // 阻塞主线程 2 秒钟来保证 JVM 存活
}

fun coroutineBlock() {
    GlobalScope.launch { // 在后台启动一个新的协程并继续
        delay(1000L)
        println("World!")
    }
    println("Hello,") // 主线程中的代码会立即执行
    runBlocking {     // 但是这个表达式阻塞了主线程
        delay(2000L)  // ……我们延迟 2 秒来保证 JVM 的存活
    }
}

fun coroutineRunBlocking() =  runBlocking<Unit> { // 开始执行主协程
    GlobalScope.launch { // 在后台启动一个新的协程并继续
        delay(1000L)
        println("World!")
    }
    println("Hello,") // 主协程在这里会立即执行
    delay(2000L)      // 延迟 2 秒来保证 JVM 存活
}

fun coroutineExampleRun() = runBlocking {
    coroutineExample()
}

suspend fun coroutineExample() {
    val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job
        delay(1000L)
        println("World!")
    }
    println("Hello,")
    job.join() // wait until child coroutine completes
}

// coroutineScope 构建器声明自己的作用域。它会创建一个协程作用域并且在所有已启动子协程执行完毕之前不会结束。
fun coroutineRun() = runBlocking { // this: CoroutineScope
    launch {
        delay(200L)
        println("Task from runBlocking")
    }

    coroutineScope { // 创建一个协程作用域
        launch {
            delay(500L)
            println("Task from nested launch")
        }

        delay(100L)
        println("Task from coroutine scope") // 这一行会在内嵌 launch 之前输出
    }

    println("Coroutine scope is over") // 这一行在内嵌 launch 执行完毕后才输出
}


fun main() = runBlocking {
    launch { doWorld() }
    println("Hello,")
}

// 这是你的第一个挂起函数
suspend fun doWorld() {
    delay(1000L)
    println("World!")
}

//它启动了 10 万个协程，并且在 5 秒钟后，每个协程都输出一个点。
fun coroutineLight() = runBlocking {
    var count = 0
    repeat(100_000) {
        launch {
            delay(5000L)
            count++
            println("count = $count")
        }
    }
}


fun globalCoroutine() {
    runBlocking {
        GlobalScope.launch {
            repeat(1000) { i ->
                println("I'm sleeping $i ...")
                delay(500L)
            }
        }
        delay(1300L) // 在延迟后退出
    }

}

fun coroutinesAsync() {
    println("asyncCoroutine start  ${Thread.currentThread().name}")
    val result = GlobalScope.launch(Dispatchers.Main) {
        val one = async {
            delay(1000L) // 假设我们在这里做了一些有用的事
            return@async 13
        }
        val two = async {
            delay(1000L) // 假设我们在这里也做了一些有用的事
            return@async 29
        }
        println("The answer is ${one.await() + two.await()}")
    }
    println("asyncCoroutine end  ${Thread.currentThread().name}")
}

suspend fun concurrentSum(): Int = coroutineScope {
    val one = async { doSomethingUsefulOne() }
    val two = async { doSomethingUsefulTwo() }
    one.await() + two.await()
}

fun doSomethingUsefulOne() = 13

fun doSomethingUsefulTwo() = 29

fun withContextFun() {
    CoroutineScope(Dispatchers.Main).launch {
        val time1 = System.currentTimeMillis()
        val task1 = withContext(Dispatchers.IO) {
            delay(2000)
            println("1.执行task1.... [当前线程为：${Thread.currentThread().name}]")
            "one" //返回结果赋值给task1
        }
        val task2 = withContext(Dispatchers.IO) {
            delay(1000)
            println("2.执行task2.... [当前线程为：${Thread.currentThread().name}]")
            "two" //返回结果赋值给task2
        }
        println("task1 = $task1 , task2 = $task2 , 耗时 ${System.currentTimeMillis()-time1} ms [当前线程为：${Thread.currentThread().name}]")

    }
}

fun coroutineTryCatch() {
    GlobalScope.launch {
        try {
            val job = launch {
                println("Throwing exception from launch")
                throw IndexOutOfBoundsException() // 我们将在控制台打印 Thread.defaultUncaughtExceptionHandler
            }
            job.join()
            println("Joined failed job")
            val deferred = async { // async 根协程
                println("Throwing exception from async")
                throw ArithmeticException() // 没有打印任何东西，依赖用户去调用等待
            }
            deferred.await()
            println("Unreached")
        } catch (e: Exception) {
            println("Caught $e")
        }
    }
}

fun asyncTryCatch() {
    GlobalScope.launch {
        println("async start")
        val deferred = async { // async 根协程
            try {
                println("Throwing exception from async")
                throw ArithmeticException() // 没有打印任何东西，依赖用户去调用等待
            } catch (e: Exception) {
                println("Caught 2 $e")
            }
        }
        deferred.await()
        println("Unreached")
    }
}
